import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.PopupMenu;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;
import javax.imageio.ImageIO;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.ProgressBarUI;
import javax.swing.text.Position;

/**
 * the test environment is visualized and showed at this panel
 * 
 * @author Ronny
 * 
 */
public class KomMapPane extends JPanel implements ComponentListener {

	private KomMap kommap;
	private boolean positionImageDragging = false;
	private final static String textofpostion = "Your Position";
	private static ArrayList<String> infoPos; // Vectors are synchronized.
	private int sampleprogress = 0;
	// to remove components on the panel
	private RemoveAction removeAction;
	// to clear all the components on the panel
	private ClearallAction clearallaction;
	private ImageIcon icon = new ImageIcon(this.getClass().getResource(
			"resource/sunspot.png"));
	private JButton button = new JButton(icon);
	private ArrayList<Integer> coordinate;
	private ImageIcon iconforMovingSunspot = new ImageIcon(this.getClass()
			.getResource("resource/moving_Sunspot_trans.png"));
	private JButton buttonMovingSunspot = new JButton();
	private JButton buttonfixedSunspots;
	private static final long serialVersionUID = 1L;
	private MouseListener mouseListener, postionImageListener;
	private MouseMotionListener mousemotionlistener;
	// structure used to save the reference- and fixed sunspots
	private ArrayList<Point> fixedSunspotsList = new ArrayList<Point>();
	private ArrayList<String> fixedSunspotsId = new ArrayList<String>();
	private ArrayList<Point> referenceSunspotslist = new ArrayList<Point>();
	public MouseListener popupListener, clearalllistener;
	private HashMap<String, Point> fixedSunspotsMap = new HashMap<String, Point>();
	private ActionListener waitingsamplingforTimer;
	private Timer timer;
	private JProgressBar progressbarofSampling = new JProgressBar(0, 100);
	public static boolean flagAdjustPositioning = false;
	public Integer xpos, ypos;
	public JButton buttonreferencePoints;
	public JButton refPoint;
	public MouseMotionListener mousemotionlistenerforRef;
	public boolean refPointtoServerFlag = true;
	public static JButton selectedButton;

	public KomMapPane(KomMap kommap) {
		this.kommap = kommap;
		this.setBackground(Color.BLACK);
		this.setLayout(null);
		this.setPreferredSize(new Dimension(600, 400));
		this.setMinimumSize(new Dimension(600, 400));
		this.setMaximumSize(new Dimension(600, 400));
		this.setVisible(true);
		/**
		 * 
		 if (flagAdjustPositioning == false) { this.showPosition(); }
		 */
		this.initMouseListener();
		this.dragPosImageListener();
		this.removeAction = new RemoveAction(kommap);
		this.clearallaction = new ClearallAction(kommap);
		// this.setVisible(true);
	}

	/**
	 * to paint a image on the panel
	 */
	public void paint(Graphics g) {
		super.paint(g);
		Graphics2D g2 = (Graphics2D) g;
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		// draw kommap
		Image image = Toolkit.getDefaultToolkit().getImage(
				this.getClass().getResource("resource/bb.png"));
		g2.drawImage(image, 15, 15, 755, 615, this);
		g2.dispose();
	}

	/**
	 * 
	 * @param coordinatesPixel
	 * @return
	 */
	public ArrayList getCoordinatefromServer(PositionXY coordinatesPixel) {

		remove(buttonMovingSunspot);
		buttonMovingSunspot = new JButton(iconforMovingSunspot);
		buttonMovingSunspot.setVisible(true);
		buttonMovingSunspot.setContentAreaFilled(false);
		// sensor.setFocusable( false);
		buttonMovingSunspot.setBorder(new EmptyBorder(0, 0, 0, 0));
		buttonMovingSunspot.setBounds(coordinatesPixel.getX()-7,
				coordinatesPixel.getY()-4, 40, 40);
		mouselistenerforPositionImage();
		kommap.komMapPane.add(buttonMovingSunspot);
		xpos = new Integer(coordinatesPixel.getX());
		ypos = new Integer(coordinatesPixel.getY());
		// wanderung
		// xpos=xpos/770*GUIController.roomX;
		// ypos=ypos/770*GUIController.roomY;
		kommap.komconfigpane.setXPos(xpos.toString());
		kommap.komconfigpane.setYPos(ypos.toString());
		repaint();
		return coordinate;
	}

	/**
	 * show the postion after start positioning having been clicked
	 */
	public void showPosition() {

		this.button.setBorder(new EmptyBorder(0, 0, 0, 0));
		button.setBounds(310, 100, 31, 31);
		// button.setToolTipText(name);
		kommap.komMapPane.add(button);
	}

	/**
	 * to check if adjustposition
	 */
	public void showAdjustPosition() {
		if (flagAdjustPositioning == false) {
			this.showPosition();
			flagAdjustPositioning = true;
		} else {
			flagAdjustPositioning = false;
		}

	}

	/**
	 * initmouselisnter
	 */
	public void initMouseListener() {
		mouseListener = new MouseListener() {

			@Override
			public void mouseReleased(MouseEvent e) {
			}

			@Override
			public void mousePressed(MouseEvent e) {
			}

			@Override
			public void mouseExited(MouseEvent e) {
			}

			@Override
			public void mouseEntered(MouseEvent e) {
			}

			@Override
			public void mouseClicked(MouseEvent e) {

				PointerInfo info = MouseInfo.getPointerInfo();
				Point location = info.getLocation();
				xpos = new Integer(location.x);
				ypos = new Integer(location.y);
			}
		};
	}

	/**
	 * add position button of moving sunspot
	 */
	private void addPositonButton() {
		mouselistenerforPositionImage();
		ImageIcon icon = new ImageIcon(this.getClass().getResource(
				"resource/moving_Sunspot_trans.png"));
		JButton button = new JButton(icon);
		button.setContentAreaFilled(false);
		// sensor.setFocusable( false);
		button.setBorder(new EmptyBorder(0, 0, 0, 0));
		button.setBounds(xpos.intValue(), ypos.intValue(), 31, 31);
		kommap.komMapPane.add(button);
		button.addMouseMotionListener(mousemotionlistener);
		// button.addMouseListener(postionImageListener);
		repaint();
	}

	/**
	 * read an image
	 * 
	 * @param fileLocation
	 * @return
	 */
	public static BufferedImage readImage(String fileLocation) {
		BufferedImage img = null;
		try {
			img = ImageIO.read(new File(fileLocation));
		} catch (IOException e) {
			e.printStackTrace();
		}
		return img;
	}

	/**
     * 
     */
	public void givePosiFlag() {

		if (flagAdjustPositioning == false) {
			this.addMouseListener(mouseListener);

			buttonMovingSunspot.addMouseMotionListener(mousemotionlistener);
			buttonMovingSunspot.addMouseListener(postionImageListener);
			// this.addComponentListener(this);
			flagAdjustPositioning = true;
		} else {
			this.removeMouseListener(mouseListener);

			flagAdjustPositioning = false;
		}

	}

	/**
	 * mouselistener for positioning image
	 */
	private void mouselistenerforPositionImage() {

		postionImageListener = new MouseListener() {

			@Override
			public void mouseReleased(MouseEvent e) {

				JButton button = (JButton) e.getSource();
				xpos = button.getX();
				ypos = button.getY();
				kommap.komconfigpane.setXPos(xpos.toString());
				kommap.komconfigpane.setYPos(ypos.toString());
				repaint();

			}

			@Override
			public void mousePressed(MouseEvent e) {

			}

			@Override
			public void mouseExited(MouseEvent e) {

			}

			@Override
			public void mouseEntered(MouseEvent e) {

			}

			@Override
			public void mouseClicked(MouseEvent e) {

			}
		};
	}

	/**
	 * drag the image
	 */
	private void dragPosImageListener() {

		mousemotionlistener = new MouseMotionListener() {

			@Override
			public void mouseDragged(MouseEvent e) {

				JButton c = (JButton) e.getComponent();
				int x = c.getX() + e.getX() - (c.getWidth() / 2);
				int y = c.getY() + e.getY() - (c.getHeight() / 2);
				c.setLocation(x, y);
				xpos = x;
				ypos = y;
				kommap.komconfigpane.setXPos(xpos.toString());
				kommap.komconfigpane.setYPos(ypos.toString());
				positionImageDragging = true;

			}

			@Override
			public void mouseMoved(MouseEvent e) {

			}
		};
	}

	@Override
	public void componentResized(ComponentEvent e) {

	}

	@Override
	public void componentMoved(ComponentEvent e) {

	}

	@Override
	public void componentShown(ComponentEvent e) {

	}

	@Override
	public void componentHidden(ComponentEvent e) {

	}

	/**
	 * getPositionofBeaconSenders from Server
	 * 
	 * @param coordinators
	 * @param sunspotid
	 * @return
	 */
	public HashMap<String, Point> getPositionofFixedSunspots(
			ArrayList<Point> coordinators, ArrayList<String> sunspotid) {
		int index = 0;
		while (coordinators.iterator().hasNext() && index < 5) {
			this.fixedSunspotsList.add(coordinators.get(index));
			this.fixedSunspotsId.add(sunspotid.get(index));
			this.fixedSunspotsMap.put(sunspotid.get(index),
					coordinators.get(index));
			index++;
		}

		return this.fixedSunspotsMap;
	}

	/**
	 * show the fixed sunspots on the map
	 */
	public void showFixedSunspots() {
		int index = 0;
		ImageIcon icon = new ImageIcon(this.getClass().getResource(
				"resource/Beacon_Sender_durch.png"));
		while (fixedSunspotsList.iterator().hasNext() && index < 5) {
			buttonfixedSunspots = new JButton();
			buttonfixedSunspots.setIcon(icon);
			buttonfixedSunspots.setContentAreaFilled(false);
			// sensor.setFocusable( false);
			buttonfixedSunspots.setBorder(new EmptyBorder(0, 0, 0, 0));

			buttonfixedSunspots.setBounds(fixedSunspotsList.get(index).x,
					fixedSunspotsList.get(index).y, 20, 20);
			index++;
			kommap.komMapPane.add(buttonfixedSunspots);
			repaint();
		}
	}

	/**
	 * getPositionoReferencepoints from Server
	 * 
	 * @param coordinator
	 * @param sunspotid
	 */
	public void getPositionoReferencepoints(
			ArrayList<ArrayList<Integer>> coordinator, String sunspotid) {

	}

	/**
	 * get the reference points from server
	 * 
	 * @param referencepoints
	 */
	public void showReferencePoints(ArrayList<PositionXY> referencepoints) {

		ImageIcon icon = new ImageIcon(this.getClass().getResource(
				"resource/Reference_Point_trans.png"));

		for (int index = 0; index < referencepoints.size(); index++) {
			buttonreferencePoints = new JButton();
			buttonreferencePoints.setIcon(icon);
			buttonreferencePoints.setContentAreaFilled(false);
			// sensor.setFocusable( false);
			buttonreferencePoints.setBorder(new EmptyBorder(0, 0, 0, 0));
			buttonreferencePoints.setBounds(referencepoints.get(index).getX(),
					referencepoints.get(index).getY(), 25, 25);

			// add popmenu listener;
			buttonreferencePoints.getInputMap().put(
					KeyStroke.getKeyStroke("D"), "RemoveReffromServer");
			removeAction.nameRefSer = "RemoveReffromServer";
			buttonreferencePoints.getActionMap().put("RemoveReffromServer",
					removeAction);
			popupListener = new PopupListener(
					kommap.komMapPane.clearandremovePopmenu());
			

			kommap.komMapPane.add(buttonreferencePoints);
			repaint();
		}
	}

	/**
	 * set the reference point , for the test only one reference Point can be
	 * set on the panel, the next one can be set only after the first one having
	 * been sent to server
	 */
	public void setRefPoints() {

		
		popupListener = new PopupListener(
			kommap.komMapPane.clearandremovePopmenu());

		kommap.komMapPane.addMouseListener(new MouseListener() {

			@Override
			public void mouseReleased(MouseEvent e) {

			}

			@Override
			public void mousePressed(MouseEvent e) {

			}

			@Override
			public void mouseExited(MouseEvent e) {

			}

			@Override
			public void mouseEntered(MouseEvent e) {

			}

			@Override
			public void mouseClicked(MouseEvent e) {
				// to check if the set reference point already sent to the
				// server
				if (refPointtoServerFlag&&kommap.komconfigpane.ifreferenceSet) {
					
					refPointtoServerFlag = false;
					ImageIcon icon = new ImageIcon(this.getClass().getResource(
							"resource/Reference_Point_trans.png"));
					refPoint = new JButton();
					refPoint.setIcon(icon);
					refPoint.setContentAreaFilled(false);
					refPoint.setBorder(new EmptyBorder(0, 0, 0, 0));

					System.out.print("e.position" + e.getX());
					refPoint.setBounds(e.getX(), e.getY(), 25, 25);

					// to show the reference positon on the configpanel

					xpos = refPoint.getX();
					ypos = refPoint.getY();
					kommap.komconfigpane.setXPos(xpos.toString());
					kommap.komconfigpane.setYPos(ypos.toString());

					// to implement the keystroke in order to delete the
					// reference point

					refPoint.getInputMap().put(KeyStroke.getKeyStroke("D"),
							"Remove");

					removeAction.nameRef = "Remove";
					refPoint.getActionMap().put("Remove", removeAction);
					refPoint.addMouseListener(new MouseListener() {

						@Override
						public void mouseReleased(MouseEvent e) {

						}

						@Override
						public void mousePressed(MouseEvent e) {

						}

						@Override
						public void mouseExited(MouseEvent e) {

						}

						@Override
						public void mouseEntered(MouseEvent e) {

						}

						@Override
						public void mouseClicked(MouseEvent e) {
							// get the selected component
							selectedButton = (JButton) e.getComponent();
							xpos = selectedButton.getX();
							ypos = selectedButton.getY();
							kommap.komconfigpane.setXPos(xpos.toString());
							kommap.komconfigpane.setYPos(ypos.toString());
						}
					});
                    
					//refPoint.addMouseListener(popupListener);

					mousemotionlistenerforRef = new MouseMotionListener() {

						@Override
						public void mouseMoved(MouseEvent e) {

						}

						@Override
						public void mouseDragged(MouseEvent e) {

							JButton c = (JButton) e.getComponent();
							xpos = c.getX() + e.getX() - (c.getWidth() / 2);
							ypos = c.getY() + e.getY() - (c.getHeight() / 2);
							c.setLocation(xpos, ypos);
							kommap.komconfigpane.setXPos(xpos.toString());
							kommap.komconfigpane.setYPos(ypos.toString());

						}
					};
					kommap.komMapPane.add(refPoint);
					repaint();
					refPoint.addMouseMotionListener(mousemotionlistenerforRef);

				}
			}
		});

	}

	/**
	 * JPopupMenu for the reference point
	 * 
	 * @return
	 */
	public JPopupMenu clearandremovePopmenu() {

		JPopupMenu popupMenu = new JPopupMenu();
		JMenuItem menuItemRemoveRef = new JMenuItem("Remove");

		menuItemRemoveRef.addActionListener(removeAction);
		popupMenu.add(menuItemRemoveRef);

		JMenuItem menuItemClear = new JMenuItem("Clear All");
		clearallaction.name = "Clear";
		menuItemClear.addActionListener(clearallaction);
		popupMenu.add(menuItemClear);
		JMenu menuItemDoingSamples = new JMenu(
				"Doing Samples for this Reference Point");

		// timer ActionListener
		waitingsamplingforTimer = new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				xpos = PopupListener.xpos;
				ypos = PopupListener.ypos;

				sampleprogress += 10; // set progress

				kommap.komMapPane.progressbarofSampling
						.setValue(sampleprogress);

				if (!kommap.guiController.isSamplingFinished()) {

					Component[] com = kommap.komconfigpane.getComponents();
					for (int a = 0; a < com.length; a++) {
						com[a].setEnabled(false);
					}

				} else {
					timer.stop();
					Component[] com = kommap.komconfigpane.getComponents();
					for (int a = 0; a < com.length; a++) {
						com[a].setEnabled(true);
					}
				}
			}
		};

		// new sample Table
		JMenuItem newtable = new JMenuItem("New Sample Table");
		newtable.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				xpos = PopupListener.xpos;
				ypos = PopupListener.ypos;
				boolean keepTable = false;
				JOptionPane.showMessageDialog(null,
						" Please Wait a Minute until Server finish Sampling",
						"Sampling for the Reference Point",
						JOptionPane.INFORMATION_MESSAGE);

				sampleprogress = 0;

				kommap.komMapPane.addProgressBar(xpos, ypos);
				kommap.guiController.addSamplesToReferencepoint(xpos, ypos, 10,
						keepTable);
				timer = new Timer(1000, waitingsamplingforTimer);

				// if keep the old table is clicked, a timer will be started and
				// the color of the configure panel will be changed,otherwise
				// the timer is to be started automatically

				if (timer.isRunning()) {
					timer.stop();

					timer.start();
				} else {

					timer.start();
				}
			}
		});

		menuItemDoingSamples.add(newtable);

		// keep the old table
		JMenuItem keeptable = new JMenuItem("Keep The Old Table");

		keeptable.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {

				JOptionPane.showMessageDialog(null,
						" Please Wait a Minute until Server finish Sampling",
						"Sampling for the Reference Point",
						JOptionPane.INFORMATION_MESSAGE);
				sampleprogress = 0;
				xpos = PopupListener.xpos;
				ypos = PopupListener.ypos;
				kommap.komMapPane.addProgressBar(xpos, ypos);
				boolean keepTable = true;

				if (xpos != null && ypos != null) {
					kommap.guiController.addSamplesToReferencepoint(xpos, ypos,
							10, keepTable);
				}
				timer = new Timer(1000, waitingsamplingforTimer);
				// if keep the old table is clicked, a timer will be started and
				// the color of the configure panel will be changed,otherwise
				// the timer is to be started automatically
				if (timer.isRunning()) {
					timer.stop();
					timer.start();
				} else {
					timer.start();
				}

			}
		});

		menuItemDoingSamples.add(keeptable);
		popupMenu.add(menuItemDoingSamples);
		return popupMenu;
	}

	/**
	 * add progressbar of sampling to the reference points
	 * 
	 * @param x
	 * @param y
	 * @return
	 */
	private void addProgressBar(int x, int y) {

		progressbarofSampling.setBorder(new EmptyBorder(1, 1, 1, 1));
		progressbarofSampling.setBounds(x, y - 10, 30, 10);

		kommap.komMapPane.add(progressbarofSampling);
		repaint();
		/**
		 * 
		 * to show the progress of sampling
		 */
		new Thread() {
			@Override
			public void run() {
				SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						progressbarofSampling.setValue(sampleprogress);

					}
				});
			}

		}.start();

	}

	/**
	 * 
	 * @return
	 */
	public JButton getRefPointInstance() {

		return this.buttonreferencePoints;
	}

}
